/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.uc.manager.impl;

import com.xy.biz.uc.dao.*;
import com.xy.biz.uc.domain.bo.ResourceBO;
import com.xy.biz.uc.domain.bo.RoleBO;
import com.xy.biz.uc.domain.bo.UserBO;
import com.xy.biz.uc.domain.bo.UserGroupBO;
import com.xy.biz.uc.domain.converter.ResourceConverter;
import com.xy.biz.uc.domain.converter.RoleConverter;
import com.xy.biz.uc.domain.converter.UserConverter;
import com.xy.biz.uc.domain.converter.UserGroupConverter;
import com.xy.biz.uc.domain.po.*;
import com.xy.biz.uc.domain.query.UserCodeQuery;
import com.xy.biz.uc.domain.query.UserIdQuery;
import com.xy.biz.uc.domain.query.UserQuery;
import com.xy.biz.uc.domain.req.RemoveUserGroupUserRelRequest;
import com.xy.biz.uc.manager.UserManager;
import com.xy.lang.domain.Result;
import com.xy.tool.context.UserContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 *
 * @author zsp
 * @date 2020-8-19
 */
@Service
public class UserManagerImpl implements UserManager {

    @Autowired
    private UserDao userDao;
    @Autowired
    private UserRoleRelDao userRoleRelDao;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private RoleResourceRelDao roleResourceRelDao;
    @Autowired
    private ResourceDao resourceDao;
    @Autowired
    private UserGroupUserRelDao userGroupUserRelDao;
    @Autowired
    private UserGroupRoleRelDao userGroupRoleRelDao;
    @Autowired
    private UserGroupDao userGroupDao;

    @Transactional
    @Override
    public int saveUser(UserBO userBO) {
        UserPO userPO = UserConverter.toPO(userBO);
        int affectedRows = userDao.saveUser(userPO);
        if (affectedRows > 0) {
            userBO.setUserId(userPO.getUserId());
            List<Long> roleIdList = userBO.getRoleIdList();
            if (!CollectionUtils.isEmpty(roleIdList)) {
                List<UserRoleRelPO> userRoleRelPOList
                        = roleIdList.stream().map(e -> new UserRoleRelPO(userPO.getUserId(), e)).collect(Collectors.toList());
                userRoleRelDao.saveAllUserRoleRel(userRoleRelPOList);
            }
            Long userGroupId = userBO.getUserGroupId();
            if (null != userGroupId) {
                userGroupUserRelDao.saveAllUserGroupUserRel(Arrays.asList(UserGroupUserRelPO.builder()
                        .userId(userBO.getUserId())
                        .userGroupId(userGroupId)
                        .joinStatus(1)
                        .createUserId(userBO.getCreateUserId())
                        .createTime(userBO.getCreateTime())
                        .build()));
            }
        }
        return affectedRows;
    }

    @Transactional
    @Override
    public int updateUser(UserBO userBO) {
        int affectedRows = userDao.updateUser(UserConverter.toPO(userBO));
        if (affectedRows > 0) {
            userRoleRelDao.deleteUserRoleRelByUserId(userBO.getUserId());
            List<Long> roleIdList = userBO.getRoleIdList();
            if (!CollectionUtils.isEmpty(roleIdList)) {
                List<UserRoleRelPO> userRoleRelPOList
                        = roleIdList.stream().map(e -> new UserRoleRelPO(userBO.getUserId(), e)).collect(Collectors.toList());
                userRoleRelDao.saveAllUserRoleRel(userRoleRelPOList);
            }
            userGroupUserRelDao.deleteUserGroupUserRelByUserId(userBO.getUserId());
            Long userGroupId = userBO.getUserGroupId();
            if (null != userGroupId) {
                userGroupUserRelDao.saveAllUserGroupUserRel(Arrays.asList(UserGroupUserRelPO.builder()
                        .userId(userBO.getUserId())
                        .userGroupId(userGroupId)
                        .build()));
            }
        }
        return affectedRows;
    }

    /**
     * 禁闭/解禁用户
     *
     * @param userBO
     */
    @Override
    public int lockUser(UserBO userBO) {
        return userDao.lockUser(UserConverter.toPO(userBO));
    }

    @Transactional
    @Override
    public int updateUserBaseInfo(UserBO userBO) {
        return userDao.updateUser(UserConverter.toPO(userBO));
    }

    @Transactional
    @Override
    public int deleteUser(Long userId) {
        int affectedRows = userDao.deleteUser(userId);
        if (affectedRows > 0) {
            userRoleRelDao.deleteUserRoleRelByUserId(userId);
            userGroupUserRelDao.deleteUserGroupUserRelByUserId(userId);
        }
        return affectedRows;
    }

    @Override
    public boolean isUserCodeExists(String userCode) {
        return userDao.isUserCodeExists(userCode);
    }

    @Override
    public boolean isMobileExists(String mobile) {
        return userDao.isMobileExists(mobile);
    }

    @Override
    public boolean isEmailExists(String email) {
        return userDao.isEmailExists(email);
    }

    @Override
    public UserBO getUser(UserIdQuery userIdQuery) {
        Long userId = userIdQuery.firstUserId();
        UserBO userBO = UserConverter.fromPO(userDao.getUser(userId));
        buildUserBO(userBO, userIdQuery.isWithRole(), userIdQuery.isWithResource(), userIdQuery.isWithUserGroup());
        return userBO;
    }

    @Override
    public UserBO getUserByUserCode(UserCodeQuery userCodeQuery) {
        UserBO userBO = UserConverter.fromPO(userDao.getUserByUserCode(userCodeQuery.getUserCode()));
        buildUserBO(userBO, userCodeQuery.isWithRole(), userCodeQuery.isWithResource(), userCodeQuery.isWithUserGroup());
        return userBO;
    }

    /**
     * 查找一个
     *
     * @param query
     * @return
     */
    @Override
    public UserBO getUserByName(UserQuery query) {
        UserBO userBO = UserConverter.fromPO(userDao.getUserByName(query.getUserName()));
        buildUserBO(userBO, query.isWithRole(), false, query.isWithUserGroup());
        return userBO;
    }

    @Override
    public List<UserBO> getUserByNameS(Collection<String> collection) {
        List<UserBO> userBOList = UserConverter.fromPO(userDao.getUserByNameS(collection));
        return userBOList;
    }

    private void buildUserBO(UserBO userBO, boolean isWithRole, boolean isWithResource, boolean isWithUserGroup) {
        if (userBO != null) {
            Long userId = userBO.getUserId();
            if (isWithRole || isWithResource || isWithUserGroup) {
                //查询部门-用户（一对多关系，一个部门包含多个用户）
                Map<Long, List<UserGroupUserRelPO>> userGroupUserMap = null;
                //根据用户查关系数据，一个用户对应一个部门
                List<UserGroupUserRelPO> userGroupUserRelPOList = userGroupUserRelDao.listUserGroupUserRelByUserId(Arrays.asList(userId));
                if (!CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    userGroupUserMap = userGroupUserRelPOList.stream().collect(Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId));
                }
                if (isWithRole || isWithResource) {
                    //根据用户查关系数据，一个用户可以拥有多个角色
                    List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByUserId(Arrays.asList(userId));
                    if (!CollectionUtils.isEmpty(userRoleRelPOList)) {
                        Map<Long, List<UserRoleRelPO>> roleUserMap = userRoleRelPOList.stream().collect(Collectors.groupingBy(UserRoleRelPO::getRoleId));
                        if (isWithRole) {
                            //查询角色-部门（一对多关系，一个角色可以赋予多个部门）
                            Map<Long, List<UserGroupRoleRelPO>> roleUserGroupMap = null;
                            if (!CollectionUtils.isEmpty(userGroupUserMap)) {
                                //根据部门查关系数据，一个部门可以拥有多个角色
                                List<UserGroupRoleRelPO> userGroupRoleRelPOList = userGroupRoleRelDao.listUserGroupRoleRelByUserGroupId(userGroupUserMap.keySet());
                                if (!CollectionUtils.isEmpty(userGroupRoleRelPOList)) {
                                    roleUserGroupMap = userGroupRoleRelPOList.stream().collect(Collectors.groupingBy(UserGroupRoleRelPO::getRoleId));
                                }
                            }
                            //根据“角色-用户、角色-部门，部门-用户”3个映射关系，返回用户与角色的映射关系，并为用户设置角色
                            Map<Long, Set<RoleBO>> map = findRoleForUser(roleUserMap, roleUserGroupMap, userGroupUserMap);
                            userBO.setRoleBOSet(map.get(userId));
                        }
                        if (isWithResource) {
                            Map<Long, Set<ResourceBO>> map = findResourceForUser(roleUserMap);
                            userBO.setResourceBOSet(map.get(userId));
                        }
                    }
                }
                if (isWithUserGroup && !CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                   /* Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.toMap(UserGroupUserRelPO::getUserGroupId, e -> e)));*/
                    Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId)));
                    userBO.setUserGroupBO(map.get(userId));
                }
            }
        }
    }

    @Override
    public List<UserBO> listUserById(UserIdQuery userIdQuery) {
        List<UserBO> userBOList = UserConverter.fromPO(userDao.listUserById(userIdQuery.getUserIdList()));
        if (!CollectionUtils.isEmpty(userBOList)) {
            if (userIdQuery.isWithRole() || userIdQuery.isWithResource() || userIdQuery.isWithUserGroup()) {
                //查询部门-用户（一对多关系，一个部门包含多个用户）
                Map<Long, List<UserGroupUserRelPO>> userGroupUserMap = null;
                //根据用户查关系数据，一个用户对应一个部门
                List<UserGroupUserRelPO> userGroupUserRelPOList = userGroupUserRelDao.listUserGroupUserRelByUserId(userIdQuery.getUserIdList());
                if (!CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    userGroupUserMap = userGroupUserRelPOList.stream().collect(Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId));
                }
                if (userIdQuery.isWithRole() || userIdQuery.isWithResource()) {
                    //根据用户查关系数据，一个用户可以拥有多个角色
                    List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByUserId(userIdQuery.getUserIdList());
                    if (!CollectionUtils.isEmpty(userRoleRelPOList)) {
                        Map<Long, List<UserRoleRelPO>> roleUserMap = userRoleRelPOList.stream().collect(Collectors.groupingBy(UserRoleRelPO::getRoleId));
                        if (userIdQuery.isWithRole()) {
                            //查询角色-部门（一对多关系，一个角色可以赋予多个部门）
                            Map<Long, List<UserGroupRoleRelPO>> roleUserGroupMap = null;
                            if (!CollectionUtils.isEmpty(userGroupUserMap)) {
                                //根据部门查关系数据，一个部门可以拥有多个角色
                                List<UserGroupRoleRelPO> userGroupRoleRelPOList = userGroupRoleRelDao.listUserGroupRoleRelByUserGroupId(userGroupUserMap.keySet());
                                if (!CollectionUtils.isEmpty(userGroupRoleRelPOList)) {
                                    roleUserGroupMap = userGroupRoleRelPOList.stream().collect(Collectors.groupingBy(UserGroupRoleRelPO::getRoleId));
                                }
                            }
                            //根据“角色-用户、角色-部门，部门-用户”3个映射关系，返回用户与角色的映射关系，并为用户设置角色
                            Map<Long, Set<RoleBO>> map = findRoleForUser(roleUserMap, roleUserGroupMap, userGroupUserMap);
                            for (UserBO userBO : userBOList) {
                                userBO.setRoleBOSet(map.get(userBO.getUserId()));
                            }
                        }
                        if (userIdQuery.isWithResource()) {
                            Map<Long, Set<ResourceBO>> map = findResourceForUser(roleUserMap);
                            for (UserBO userBO : userBOList) {
                                userBO.setResourceBOSet(map.get(userBO.getUserId()));
                            }
                        }
                    }
                }
                if (userIdQuery.isWithUserGroup() && !CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    /*Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.toMap(UserGroupUserRelPO::getUserGroupId, e -> e)));*/
                    Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId)));
                    for (UserBO userBO : userBOList) {
                        userBO.setUserGroupBO(map.get(userBO.getUserId()));
                    }
                }
            }
        }
        return userBOList;
    }

    @Override
    public List<UserBO> listUser(UserQuery query) {
        List<UserBO> userBOList = UserConverter.fromPO(userDao.listUser(query));
        if (!CollectionUtils.isEmpty(userBOList)) {
            if (query.isWithRole() || query.isWithUserGroup()) {
                List<Long> userIdList = userBOList.stream().map(UserBO::getUserId).collect(Collectors.toList());
                //查询部门-用户（一对多关系，一个部门包含多个用户）
                Map<Long, List<UserGroupUserRelPO>> userGroupUserMap = null;
                //根据用户查关系数据，一个用户对应一个部门
                List<UserGroupUserRelPO> userGroupUserRelPOList = userGroupUserRelDao.listUserGroupUserRelByUserId(userIdList);
                if (!CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    userGroupUserMap = userGroupUserRelPOList.stream().collect(Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId));
                }
                if (query.isWithRole()) {
                    //查询角色-部门（一对多关系，一个角色可以赋予多个部门）
                    Map<Long, List<UserGroupRoleRelPO>> roleUserGroupMap = null;
                    if (!CollectionUtils.isEmpty(userGroupUserMap)) {
                        //根据部门查关系数据，一个部门可以拥有多个角色
                        List<UserGroupRoleRelPO> userGroupRoleRelPOList = userGroupRoleRelDao.listUserGroupRoleRelByUserGroupId(userGroupUserMap.keySet());
                        if (!CollectionUtils.isEmpty(userGroupRoleRelPOList)) {
                            roleUserGroupMap = userGroupRoleRelPOList.stream().collect(Collectors.groupingBy(UserGroupRoleRelPO::getRoleId));
                        }
                    }
                    //根据用户查关系数据，一个用户可以拥有多个角色
                    List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByUserId(userIdList);
                    if (!CollectionUtils.isEmpty(userRoleRelPOList)) {
                        Map<Long, List<UserRoleRelPO>> roleUserMap = userRoleRelPOList.stream().collect(Collectors.groupingBy(UserRoleRelPO::getRoleId));
                        //根据“角色-用户、角色-部门，部门-用户”3个映射关系，返回用户与角色的映射关系，并为用户设置角色
                        Map<Long, Set<RoleBO>> map = findRoleForUser(roleUserMap, roleUserGroupMap, userGroupUserMap);
                        for (UserBO userBO : userBOList) {
                            userBO.setRoleBOSet(map.get(userBO.getUserId()));
                        }
                    }
                }
                if (query.isWithUserGroup() && !CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    //设置用户部门，用户只隶属一个部门
                    /*Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.toMap(UserGroupUserRelPO::getUserGroupId, e -> e)));*/
                    //一个部门可以有多个用户
                    Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId)));
                    for (UserBO userBO : userBOList) {
                        userBO.setUserGroupBO(map.get(userBO.getUserId()));
                    }
                }
            }
        }

        return userBOList;
    }

    @Override
    public int countUser(UserQuery query) {
        return userDao.countUser(query);
    }

    private Map<Long, Set<RoleBO>> findRoleForUser(Map<Long, List<UserRoleRelPO>> roleUserMap,
                                                   Map<Long, List<UserGroupRoleRelPO>> roleUserGroupMap,
                                                   Map<Long, List<UserGroupUserRelPO>> userGroupUserMap) {
        //查询所有用户和所有部门的角色
        Set<Long> roleIdSet = new HashSet<>();
        roleIdSet.addAll(roleUserMap.keySet());
        if (!CollectionUtils.isEmpty(roleUserGroupMap)) {
            roleIdSet.addAll(roleUserGroupMap.keySet());
        }
        List<RoleBO> roleBOList = RoleConverter.fromPO(roleDao.listRoleById(roleIdSet));
        if (!CollectionUtils.isEmpty(roleBOList)) {
            Map<Long, Set<RoleBO>> userRoleMap = new HashMap<>();
            for (RoleBO roleBO : roleBOList) {
                //设置用户的角色
                List<UserRoleRelPO> roleUserMapMember = roleUserMap.get(roleBO.getRoleId());
                if (!CollectionUtils.isEmpty(roleUserMapMember)) {
                    for (UserRoleRelPO userRoleRelPO : roleUserMapMember) {
                        Set<RoleBO> set = userRoleMap.computeIfAbsent(userRoleRelPO.getUserId(), e -> new HashSet<>());
                        set.add(roleBO);
                    }
                }
                //设置部门的角色给部门里的用户
                if (!CollectionUtils.isEmpty(roleUserGroupMap) && !CollectionUtils.isEmpty(userGroupUserMap)) {
                    List<UserGroupRoleRelPO> roleUserGroupMapMember = roleUserGroupMap.get(roleBO.getRoleId());
                    if (!CollectionUtils.isEmpty(roleUserGroupMapMember)) {
                        //遍历角色的部门，根据部门找到其用户
                        for (UserGroupRoleRelPO userGroupRoleRelPO : roleUserGroupMapMember) {
                            List<UserGroupUserRelPO> userGroupUserMapMember = userGroupUserMap.get(userGroupRoleRelPO.getUserGroupId());
                            if (!CollectionUtils.isEmpty(userGroupUserMapMember)) {
                                //遍历部门的用户，设置部门的角色给用户
                                for (UserGroupUserRelPO userGroupUserRelPO : userGroupUserMapMember) {
                                    Set<RoleBO> set = userRoleMap.computeIfAbsent(userGroupUserRelPO.getUserId(), e -> new HashSet<>());
                                    set.add(roleBO);
                                }
                            }
                        }
                    }
                }
            }
            return userRoleMap;
        }

        return Collections.emptyMap();
    }

    private Map<Long, Set<ResourceBO>> findResourceForUser(Map<Long, List<UserRoleRelPO>> relGroup) {
        List<RoleResourceRelPO> roleResourceRelPOList = roleResourceRelDao.listRoleResourceRelByRoleId(relGroup.keySet());
        if (!CollectionUtils.isEmpty(roleResourceRelPOList)) {
            Map<Long, List<RoleResourceRelPO>> resourceGroup = roleResourceRelPOList.stream().collect(Collectors.groupingBy(RoleResourceRelPO::getResourceId));
            List<ResourceBO> resourceBOList = ResourceConverter.fromPO(resourceDao.listResourceById(resourceGroup.keySet()));
            if (!CollectionUtils.isEmpty(resourceBOList)) {
                Map<Long, Set<ResourceBO>> userWithResourceMap = new HashMap<>();
                for (ResourceBO resourceBO : resourceBOList) {
                    List<RoleResourceRelPO> resourceGroupMember = resourceGroup.get(resourceBO.getResourceId());
                    if (!CollectionUtils.isEmpty(resourceGroupMember)) {
                        for (RoleResourceRelPO roleResourceRelPO : resourceGroupMember) {
                            List<UserRoleRelPO> relGroupMember = relGroup.get(roleResourceRelPO.getRoleId());
                            if (!CollectionUtils.isEmpty(relGroupMember)) {
                                for (UserRoleRelPO userRoleRelPO : relGroupMember) {
                                    Set<ResourceBO> set = userWithResourceMap.computeIfAbsent(userRoleRelPO.getUserId(), e -> new HashSet<>());
                                    set.add(resourceBO);
                                }
                            }
                        }
                    }
                }
                return userWithResourceMap;
            }
        }

        return Collections.emptyMap();
    }

   /* private Map<Long, UserGroupBO> findUserGroupForUser(Map<Long, UserGroupUserRelPO> relGroup) {
        List<UserGroupBO> userGroupBOList = UserGroupConverter.fromPO(userGroupDao.listUserGroupById(relGroup.keySet()));
        if (!CollectionUtils.isEmpty(userGroupBOList)) {
            Map<Long, UserGroupBO> userWithUserGroupMap = new HashMap<>();
            for (UserGroupBO userGroupBO : userGroupBOList) {
                UserGroupUserRelPO relGroupMember = relGroup.get(userGroupBO.getUserGroupId());
                if (relGroupMember != null) {
                    userWithUserGroupMap.put(relGroupMember.getUserId(), userGroupBO);
                }
            }
            return userWithUserGroupMap;
        }

        return Collections.emptyMap();
    }*/

    /**
     * @author Greekn Zhang
     * @date 2021/5/7 10:54
     * @param relGroup
     * @return java.util.Map<java.lang.Long, com.xy.biz.uc.domain.bo.UserGroupBO>
     * @description 微调后，将部门加入用户的部门属性中
     */
    private Map<Long, UserGroupBO> findUserGroupForUser(Map<Long, List<UserGroupUserRelPO>> relGroup) {
        List<UserGroupBO> userGroupBOList = UserGroupConverter.fromPO(userGroupDao.listUserGroupById(relGroup.keySet()));
        if (!CollectionUtils.isEmpty(userGroupBOList)) {
            Map<Long, UserGroupBO> userWithUserGroupMap = new HashMap<>();
            for (UserGroupBO userGroupBO : userGroupBOList) {
                List<UserGroupUserRelPO> relGroupMember = relGroup.get(userGroupBO.getUserGroupId());
                for (UserGroupUserRelPO userRelPO : relGroupMember) {
                    userWithUserGroupMap.put(userRelPO.getUserId(), userGroupBO);
                }
            }
            return userWithUserGroupMap;
        }

        return Collections.emptyMap();
    }

    @Override
    public List<UserBO> listUserByRoleId(Collection<Long> collection) {
        if (CollectionUtils.isEmpty(collection)) {
            return Collections.emptyList();
        }
        List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByRoleId(collection);
        if (CollectionUtils.isEmpty(userRoleRelPOList)) {
            return Collections.emptyList();
        }
        Set<Long> userIdSet = userRoleRelPOList.stream().map(UserRoleRelPO::getUserId).collect(Collectors.toSet());
        List<UserBO> userBOList = UserConverter.fromPO(userDao.listUserById(userIdSet));
        return userBOList;
    }

    @Override
    public List<Long> listRoleIdByUserId(Long userId) {
        List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByUserId(Arrays.asList(userId));
        if (!CollectionUtils.isEmpty(userRoleRelPOList)) {
            return userRoleRelPOList.stream().map(UserRoleRelPO::getRoleId).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    @Override
    public int saveUserGroupUser(Long userGroupId, Long userId) {
        return userGroupUserRelDao.saveAllUserGroupUserRel(Arrays.asList(UserGroupUserRelPO.builder()
                .userGroupId(userGroupId)
                .userId(userId)
                .createUserId(UserContextHolder.getUserId())
                .createTime(LocalDateTime.now())
                .joinTime(LocalDateTime.now())
                .joinStatus(1)
                .build()));
    }

    @Override
    public int deleteUserGroupUser(Long userId) {
        return userGroupUserRelDao.deleteUserGroupUserRelByUserId(userId);
    }

    @Override
    public Long getUserGroupId(Long userId) {
        List<UserGroupUserRelPO> userGroupUserRelPOList = userGroupUserRelDao.listUserGroupUserRelByUserId(Arrays.asList(userId));
        if (!CollectionUtils.isEmpty(userGroupUserRelPOList)) {
            return userGroupUserRelPOList.get(0).getUserGroupId();
        }
        return null;
    }

    @Override
    public List<UserBO> searchUser(UserQuery userQuery) {
        return UserConverter.fromPO(userDao.searchUser(userQuery));
    }

    @Override
    public int countSearchUser(UserQuery query) {
        return userDao.countSearchUser(query);
    }

    @Override
    public List<UserBO> getUsersByGroupId(Long userGroupId) {
        List<Long> userGroups = new ArrayList<>();
        userGroups.add(userGroupId);
        List<UserGroupUserRelPO> userGroupUserRelPOS = userGroupUserRelDao.listUserGroupUserRelByUserGroupId(userGroups);
        if (CollectionUtils.isEmpty(userGroupUserRelPOS)) {
            return null;
        }
        Set<Long> collect = userGroupUserRelPOS.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
        List<UserPO> userPOS = userDao.listUserById(collect);
        if (CollectionUtils.isEmpty(userPOS)) {
            return null;
        }
        List<UserBO> userBOList = UserConverter.fromPO(userPOS);
        return userBOList;
    }

    @Override
    public List<UserBO> getUsersByGroupIds(Collection<Long> userGroupIds) {
        List<UserGroupUserRelPO> userGroupUserRelPOS = userGroupUserRelDao.listUserGroupUserRelByUserGroupId(userGroupIds);
        if (CollectionUtils.isEmpty(userGroupUserRelPOS)) {
            return null;
        }
        List<Long> collect = userGroupUserRelPOS.stream().map(e -> e.getUserId()).collect(Collectors.toList());
        List<UserPO> userPOS = userDao.listUserById(collect);
        if (CollectionUtils.isEmpty(userPOS)) {
            return null;
        }
        List<UserBO> userBOS = UserConverter.fromPO(userPOS);
        UserIdQuery userIdQuery = UserIdQuery.builder().userIdList(collect).withRole(false).withResource(false).withUserGroup(true).build();
        if (!CollectionUtils.isEmpty(userBOS)) {
            if (userIdQuery.isWithRole() || userIdQuery.isWithResource() || userIdQuery.isWithUserGroup()) {
                //查询部门-用户（一对多关系，一个部门包含多个用户）
                Map<Long, List<UserGroupUserRelPO>> userGroupUserMap = null;
                //根据用户查关系数据，一个用户对应一个部门
                List<UserGroupUserRelPO> userGroupUserRelPOList = userGroupUserRelDao.listUserGroupUserRelByUserId(userIdQuery.getUserIdList());
                if (!CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    userGroupUserMap = userGroupUserRelPOList.stream().collect(Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId));
                }
                if (userIdQuery.isWithRole() || userIdQuery.isWithResource()) {
                    //根据用户查关系数据，一个用户可以拥有多个角色
                    List<UserRoleRelPO> userRoleRelPOList = userRoleRelDao.listUserRoleRelByUserId(userIdQuery.getUserIdList());
                    if (!CollectionUtils.isEmpty(userRoleRelPOList)) {
                        Map<Long, List<UserRoleRelPO>> roleUserMap = userRoleRelPOList.stream().collect(Collectors.groupingBy(UserRoleRelPO::getRoleId));
                        if (userIdQuery.isWithRole()) {
                            //查询角色-部门（一对多关系，一个角色可以赋予多个部门）
                            Map<Long, List<UserGroupRoleRelPO>> roleUserGroupMap = null;
                            if (!CollectionUtils.isEmpty(userGroupUserMap)) {
                                //根据部门查关系数据，一个部门可以拥有多个角色
                                List<UserGroupRoleRelPO> userGroupRoleRelPOList = userGroupRoleRelDao.listUserGroupRoleRelByUserGroupId(userGroupUserMap.keySet());
                                if (!CollectionUtils.isEmpty(userGroupRoleRelPOList)) {
                                    roleUserGroupMap = userGroupRoleRelPOList.stream().collect(Collectors.groupingBy(UserGroupRoleRelPO::getRoleId));
                                }
                            }
                            //根据“角色-用户、角色-部门，部门-用户”3个映射关系，返回用户与角色的映射关系，并为用户设置角色
                            Map<Long, Set<RoleBO>> map = findRoleForUser(roleUserMap, roleUserGroupMap, userGroupUserMap);
                            for (UserBO userBO : userBOS) {
                                userBO.setRoleBOSet(map.get(userBO.getUserId()));
                            }
                        }
                        if (userIdQuery.isWithResource()) {
                            Map<Long, Set<ResourceBO>> map = findResourceForUser(roleUserMap);
                            for (UserBO userBO : userBOS) {
                                userBO.setResourceBOSet(map.get(userBO.getUserId()));
                            }
                        }
                    }
                }
                if (userIdQuery.isWithUserGroup() && !CollectionUtils.isEmpty(userGroupUserRelPOList)) {
                    /*Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.toMap(UserGroupUserRelPO::getUserGroupId, e -> e)));*/
                    Map<Long, UserGroupBO> map = findUserGroupForUser(userGroupUserRelPOList.stream().collect(
                            Collectors.groupingBy(UserGroupUserRelPO::getUserGroupId)));
                    for (UserBO userBO : userBOS) {
                        userBO.setUserGroupBO(map.get(userBO.getUserId()));
                    }
                }
            }
        }
        return userBOS;
    }

    @Override
    public int removeUserGroupUserRel(RemoveUserGroupUserRelRequest request) {
        return userGroupUserRelDao.deleteUserGroupUserRelByUserIdAndUserGroupId(request);
    }

    @Override
    public Collection<Long> listUserIdByUserGroupId(Collection<Long> collection) {
        List<UserGroupUserRelPO> userGroupUserRelPOS = userGroupUserRelDao.listUserGroupUserRelByUserGroupId(collection);
        return userGroupUserRelPOS.stream().map(e -> e.getUserId()).collect(Collectors.toSet());
    }
}
